package com.yima.baseproj.security.utils.jwt;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.*;

/**
 * @Author 一码
 * @createDate 2023/4/1 09:00
 * @contact 1424529270@qq.com
 */
@Slf4j
public class JwtUtil {

    //秘钥
    private static final String KEY = "6ae854633d7f46f48c5c34fa62f85380";

    //签名人
    public static final String ISSUSER = "yanwei";

    /**
     * 得到token
     *
     * @param client 平台
     * @return
     */
    public static String createToken(String userId,String client) {
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");
        header.put("timestamp", createTimestamp());
        header.put("noncestr", createNonceStr());

        SecretKey secret = createKey();
        String jwtId = getJwtId();
        // 下面就是在为payload添加各种标准声明和私有声明了
        String token = Jwts.builder()
                .setHeader(header)
                .setId(getJwtId()) //id
                .setIssuer(ISSUSER)
                .setSubject(userId)
                .setAudience(client)
                .setIssuedAt(new Date()) //签约日期
//                .setExpiration(new Date(now + (long) 1000 * 60 * 60 * 24 * day)) //设置过期时间
                .signWith(SignatureAlgorithm.HS512, secret) //签名
                .compact();
        return token;
    }

    /**
     * 校验token.包含token过期
     * @return
     */
    public static Boolean checkToken(String token){
        try {
            SecretKey key = createKey();  //签名秘钥
            Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token);
            return true;
        }catch (SignatureException ex){
            ex.printStackTrace();
            log.error("签名失败-签名异常");
        }catch (ExpiredJwtException ex){
            ex.printStackTrace();
            log.error("签名失败-token过期");
        }catch (Exception ex){
            ex.printStackTrace();
            log.error("签名失败-其他原因");
        }
        return false;
    }

    /**
     * 获取body数据
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static Claims getBodyByToken(String token) {
        SecretKey key = createKey();
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(token).getBody();
        return claims;
    }

    /**
     * 创建秘钥
     *
     * @return
     * @throws Exception
     */
    public static SecretKey createKey() {
        try {
            byte[] encodedKey = cn.hutool.core.codec.Base64.decode(KEY);
            SecretKeySpec key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
            return key;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取jwtId
     * @return
     */
    public static String getJwtId(){
        return UUID.randomUUID().toString().replace("-","");
    }

    /**
     * 获取当前时间戳，单位秒
     * 对应【timeStamp】字段
     * @return
     */
    public static long createTimestamp() {
        return System.currentTimeMillis()/1000;
    }

    /**
     * 创建随机字符串
     * 对应字段：nonceStr
     *
     * @return String 随机字符串
     */
    public static String createNonceStr() {
        String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        Random RANDOM = new SecureRandom();
        char[] nonceChars = new char[32];
        for (int index = 0; index < nonceChars.length; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }

    public static void main(String[] args) {
        String token = JwtUtil.createToken("1111","ADMIN");
        log.info("创建token：{}",token);
        log.info("校验token：{}",JwtUtil.checkToken(token));
        log.info("获取body：{}", JwtUtil.getBodyByToken(token));
    }
}
